from __future__ import absolute_import
import logging
from os.path import join
from forest.api import Command, get_tool, types

logger = logging.getLogger('forest.commands.Dracut')

class DracutConfiguration(types.ConfigurationType):

    lists = [ 'dracutmodules' 'omit_dracutmodules', 'add_dracutmodules',
    'drivers' 'add_drivers', 'omit_drivers', 'install_items', 'filesystems',
    'fw_dir' 'add_fstab', ]

    quoted = ['mdadmconf', 'lvmconf', 'hostonly', 'do_strip', 'no_kernel',
    'drivers_dir', 'tmpdir', 'use_fstab', 'nofscks', 'kernel_only', 'no_kernel',
    'stdloglvl', 'sysloglvl', 'show_modules']

    #http://www.kernel.org/pub/linux/utils/boot/dracut/dracut.html#dracut.kernel
    #example file has them unquoted. but looking at the spec,
    #looks like there shouldn't be any unquoted. leaving for now.

    unquoted = ['logfile', 'fileloglvl']

    def __init__(self, config, value):

        super(DracutConfiguration, self).__init__(config, value)

        # options to render
        self.options = {}

        # a dict containing dracut options, bools must be represented as yes/no
        for key, val in value.iteritems():

            if isinstance(val, bool):
                val = 'yes' if val else 'no'

            self.options[key] = val

    def validate():
        pass


    @staticmethod
    def format_list(format_str, mod_list):
        if isinstance(mod_list, str):
            return format_str.format(mod_list.strip('\'\"\n'))
        elif mod_list != []:
            return format_str.format(' '.join(mod_list))
        else:
            return ''

    def get_dracut_configuration(self): #, existing=None):
        ''' returns a string approriate for /etc/dracut.conf '''
        dracut_lst = []

        #if spec is to be believed, format of 'fscks' list is an exception
        #all the others use +=, this one doesnt. ridiculous inconsistency
        #unless it's just a typo.
        for key, val in self.options.items():
            if key == 'fscks':
                dracut_lst.append(self.format_list('fscks={}\n', val))
            elif key in self.quoted:
                dracut_lst.append('{0}="{1}"\n'.format(key, val))
            elif key in self.unquoted:
                dracut_lst.append('{0}={1}\n'.format(key, val))
            elif key in self.lists:
                dracut_lst.append(self.format_list('%s+={}\n' % key, val))

        return ''.join(dracut_lst)

class Dracut(Command):
    ''' configures dracut, generating /etc/dracut.conf
    '''
    __register__ = 'commands.setup.Dracut'

    def run(self, config):
        # XXX: Not sure why lvm support is off here. I think we could leave it on.
        self.config = config.get_type(DracutConfiguration, 'dracut', DracutConfiguration(config, {'lvmconf':False}))

        dracut_path = config.join_install_root('etc', 'dracut.conf')

        get_tool('files.write') (dracut_path, self.config.get_dracut_configuration())
